package com.hd.vue2204.fm.config;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hd.vue2204.fm.entity.User;
import com.hd.vue2204.fm.service.UserService;
import com.hd.vue2204.fm.utils.ApplicationContextUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.stream.Collectors;

/*
* 使用shiro时需要提供一个自定义Realm对象，用于向shiro提供 身份信息和权限信息
* */
@Slf4j
public class CustomRealm extends AuthorizingRealm {
    @Autowired
    UserService userService;

    /**
     * 该方法用于获取当前用户的角色和权限信息
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    /**
     * 该方法提供用户的身份认证信息
     * 包含用户的密码
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @SneakyThrows
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        /*//获取用户名
        String username = (String) token.getPrincipal();
        //根据用户名查询数据库用户信息
        User dbuser = userService.getOne(new QueryWrapper<User>().eq("username", username));
        if (dbuser==null){
            throw new RuntimeException("用户不存在,登录失败");
        }*/

        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
        //获取当前请求中页面传递过来的用户名
        String userName = usernamePasswordToken.getUsername();
        //根据 token对象中的用户名，查询该用户对应的信息（一定要包含该用户名的真正的密码)
        User user=getUserFromDB (userName);
        //判断user是否为null
        if (user==null){
            //用户名不存在
            throw new Exception("用户名不存在");
        }
        //注意:校验密码的过程，不需要我们自己写代码了，只要把该用户数据库中的密码传给shiro即可，shiro后犊的流程中会校验
        //需要我们返会AuthenticationInfo对象即可
        /*
                构造函数中的参数
                参数1:代表当前用户的身份信息的对象，可以放入user对象也可以放入用户名
                参数2:数据库中的密码
                参数3;盐，注意类型需要与shiro的参数类型匹配，固定写法ByteSource.Util.bytes (user.getSalt())
                参数4:当前realm的名字，固定写法
          */
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
                user,
                user.getPassword()
                ,ByteSource.Util.bytes(user.getSalt())
                ,getName());

        return simpleAuthenticationInfo;
    }

    /**
     * 从数据库中查询用户信息
     * @param username
     * @return
     */
    private User getUserFromDB(String username) {
        /* User user = new User();
       QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("username",username);
        Map<String, Object> map = userService.getMap(wrapper);
        System.out.println(map);
        user.setId((Integer) map.get("id"));
        user.setUsername(username);
        user.setPassword((String) map.get("password"));*/
       /* user.setEmail((String) map.get("email"));
        user.setPhone((String) map.get("phone"));*/
        UserService userService = ApplicationContextUtils.getBean(UserService.class);
        User user = userService.getOne(new QueryWrapper<User>().eq("username", username));
        return user;
    }
}
